/*
 * VotingHelper.cpp
 *
 *  Created on: Oct 15, 2011
 *      Author: kimi
 */
#include "VotingHelper.h"

VotingHelper::VotingHelper(Properties *_props) {
	props = _props;
}

VotingHelper::~VotingHelper() {

}

vector<Lista> VotingHelper::getListasParaEleccionYDistrito(unsigned long eleccionId,unsigned long distritoId){
	vector<Lista> listas;

//	cout << "Obteniendo listas. Eleccion: "<< eleccionId << " - Distrito: " << distritoId<< endl;

	BlocksFile* archivoListas = NULL;

	string str_ = props->get("workingPath")
			+ props->get("ArchivoListas") + "Records";
	archivoListas = new BlocksFile(str_,props->getInt("ArchivoListasBlockSize"));


	ExtensibleHash* archivoElecciones = NULL;

	string str = props->get("workingPath")
			+ props->get("ArchivoElecciones");
	archivoElecciones = new ExtensibleHash(str,
			props->getInt("ArchivoEleccionesBlockSize"));


	char* lrec = NULL;
	unsigned long lreclen = 0;

	// recorro todas las listas, si son de la eleccion actual, luego verifico el distrito
	Block* block = NULL;
	for (unsigned long li = 0; li < archivoListas->getBlocksCount(); li++) {

		if (archivoListas->getBlockById(li,&block)) {

			for (unsigned long recId = 0; recId < block->getRecordCount(); recId++) {
				if (lrec != NULL) {
					free(lrec);
					lrec = NULL;
				}
				if (block->getRecord(recId,&lrec,&lreclen)) {

					Lista l;
					if (l.unpack(lrec+sizeof(unsigned long),lreclen- sizeof(unsigned long))) {

						if (l.getIdEleccion() == eleccionId) {
							// obtenemos la eleccion, y verificamos el distrito
							//obtengo lista por eleccion
							char* eRec = NULL;
							unsigned long eRecLen = 0;
							if (archivoElecciones->get(eleccionId,&eRec,&eRecLen) == false) {
								cerr << "No se pudo obtener la eleccion." << endl;
								if (eRec != NULL) {
									free(eRec);
									eRec = NULL;
								}
								continue;
							}

							//filtro lista por distrito
							Eleccion e;
							if (e.unpack(eRec,eRecLen) == false) {
								cerr << "No se pudo obtener la eleccion." << endl;
								if (eRec != NULL) {
									free(eRec);
									eRec = NULL;
								}
								continue;
							}

							for (unsigned long d1  = 0; d1 < e.getDistritos().size();d1++){
								if (e.getDistritos().at(d1) == distritoId) {
									listas.push_back(l);

		//							cout << "Eleccion: " << eleccionId << " - Distrito: "<< distritoId << " - Lista: "<< l.getId() << endl;

									break;
								}
							}

							if (eRec != NULL) {
								free(eRec);
								eRec = NULL;
							}
						}
					}
				}
			}
			if (lrec != NULL) {
				free(lrec);
				lrec = NULL;
			}
		}

		if (block != NULL) {
			delete block;
			block = NULL;
		}
	}

	delete archivoElecciones;
	delete archivoListas;

	return listas;
}

vector<Distrito> VotingHelper::getDistritosParaEleccion(Eleccion e) {
	vector<Distrito> distritos;

	return distritos;
}

vector<Eleccion> VotingHelper::getTodasLasElecciones() {
	vector<Eleccion> elecciones;

	//obtengo las elecciones en las que participo el votante
	unsigned long eleccionBlockSize = props->getInt("ArchivoEleccionesBlockSize");
	string eleccionRecordPath = props->get("workingPath") + props->get("ArchivoElecciones") + "Records";
	HashRecord *archivoElecciones = new HashRecord(eleccionRecordPath,eleccionBlockSize);

	for (unsigned int i = 0; i < archivoElecciones->size(); i++) {
		Block* block = NULL;
		if (archivoElecciones->getBlockByBlockId(i,&block)) {

			for (unsigned j = 0; j < block->getRecordCount(); j++) {
				char* record = NULL;
				unsigned long recordSize =0;

				if (block->getRecord(j,&record,&recordSize)) {

					Eleccion *e = new Eleccion();
					// corregimos un "sizeof(unsigned long)" porque en este registro el primer campo es el ID
					// es un registro del HASH, ojo...
					e->unpack(record+sizeof(unsigned long),recordSize-sizeof(unsigned long));

					elecciones.push_back(*e);

					delete e;
				}
				free(record);
			}

			delete block;
		}
	}

	delete archivoElecciones;
	return elecciones;
}


vector<Eleccion> VotingHelper::getEleccionesDisponiblesParaVotante(Votante* votante) {
	vector<Eleccion> elecciones;

	//obtengo las elecciones en las que participo el votante
	unsigned long eleccionBlockSize = props->getInt("ArchivoEleccionesBlockSize");
	string eleccionRecordPath = props->get("workingPath") + props->get("ArchivoElecciones") + "Records";
	HashRecord *archivoElecciones = new HashRecord(eleccionRecordPath,eleccionBlockSize);

	unsigned long distritoVotante = votante->getDistritoId();

	for (unsigned int i = 0; i < archivoElecciones->size(); i++) {
		Block* block = NULL;
		if (archivoElecciones->getBlockByBlockId(i,&block)) {

			for (unsigned j = 0; j < block->getRecordCount(); j++) {
				char* record = NULL;
				unsigned long recordSize =0;

				if (block->getRecord(j,&record,&recordSize)) {

					Eleccion *e = new Eleccion();
					// corregimos un "sizeof(unsigned long)" porque en este registro el primer campo es el ID
					// es un registro del HASH, ojo...
					e->unpack(record+sizeof(unsigned long),recordSize-sizeof(unsigned long));

					unsigned long idEleccion = e->getId();

					bool found = false;

					unsigned long qtyEleccionesVotante = votante->getElecciones().size();

					for (unsigned k = 0; k < qtyEleccionesVotante && found == false; k++) {
						unsigned long e2 = votante->getElecciones().at(k);

						if (e2 == idEleccion) {
							found = true;
							break;
						}
					}

					// si el votante no votó en esta elección, verifico que pueda votar
					bool canVote = false;
					if (found == false) {
						unsigned long qtyDistritosEleccion = e->getDistritos().size();
						for (unsigned l = 0; l < qtyDistritosEleccion; l++) {
							unsigned long dist = e->getDistritos().at(l);

							if (dist == distritoVotante) {
								canVote = true;
								break;
							}
						}
					}

					if (found == false && canVote == true) {
						elecciones.push_back(*e);
					}

					delete e;
				}

				free(record);
			}

			delete block;
		}
	}

	delete archivoElecciones;
	return elecciones;
}

vector<Candidato> VotingHelper::getCandidatosEnLista(unsigned long idLista){
	vector<Candidato> candidatos;
	unsigned long candidatosBlockSize = props->getInt("ArchivoCandidatosBlockSize");
	string candidatosRecordPath = props->get("workingPath") + props->get("ArchivoCandidatos") + "Records";
	HashRecord *archivoCandidatos = new HashRecord(candidatosRecordPath,candidatosBlockSize);

	for (unsigned int i = 0; i < archivoCandidatos->size(); i++) {
		Block* block = NULL;
		if (archivoCandidatos->getBlockByBlockId(i,&block)) {
			for (unsigned j = 0; j < block->getRecordCount(); j++) {
				char* record = NULL;
				unsigned long recordSize =0;
				if (block->getRecord(j,&record,&recordSize)) {
					Candidato *c = new Candidato();
					
					c->unpack(record+sizeof(unsigned long),recordSize-sizeof(unsigned long));
					
					unsigned long idLista2 = c->getIdLista();
					if (idLista == idLista2) {
						unsigned long idVotante = c->getIdVotante();
						candidatos.push_back(*c);
						break;
					}
				delete c;
				}
				free(record);
			}
			delete block;
		}
	}
	delete archivoCandidatos;
	return candidatos;
}

